前言
Unsafe可以用于获取成员字段在类实例中的偏移量,直接操作变量在主内存中的值等操作,是实现原子类的关键。
jdk示例
unsafe.objectFieldOffset(Field f)方法,获取成员变量地址偏移量
以jdk AtomicInteger类的具体实现为例,进行说明:public class AtomicInteger extends Number implements java.io.Serializable {
private static final longserialVersionUID = 6214790243416807050L;
// 获取Unsafe实例
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile int value;
//value字段相对AtomicInteger对象内存地址的偏移量
private static final longvalueOffset;
static {
try {
//类初始化时,计算value字段相对AtomicInteger对象内存地址的偏移量量
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { thrownew Error(ex); }
}
}
unsafe.compareAndSwapInt 比较并修改主内存中对象字段的值
以jdk AtomicBoolean类的具体实现为例,进行说明://boolean类型在jvm中,使用int类型来表达的,占4字节
public class AtomicBoolean implements java.io.Serializable {
public final boolean get() {
return value != 0;
}
public final boolean compareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
//this:修改当前对象,字段偏移量为valueOffset的值,其中expect为主内存中期望值,update为待更新值
//如果与期望的值相等,则更新主内存该对象中字段值为update,并返回true
//更新失败,则返回false
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
}
根据字段偏移量获取实例中此字段的值
|
获取Unsafe实例
/**import sun.misc.Unsafe;导入此包 |
总结
Unsafe类提供了直接操作主内存(堆内存)的方法,但sun公司是通过安全管理器限制了直接获取Unsafe的,毕竟应用层直接操作主内存是不安全的,当然也是不允许的,由于篇幅有限,以上只是介绍了Unsafe类中比较常用的方法。